#include "../include/chat_page.h"
#include "../include/comm.h"
#include "../include/dict.h"

#define EMOJI_SEND_FOLDER_PATH "/mnt/hgfs/share/chat_client_pc1/emoji_send"
#define EMOJI_RECV_FOLDER_PATH "/mnt/hgfs/share/chat_client_pc1/emoji_recv"

static lv_ft_info_t info;
static lv_style_t style;

lv_obj_t *chat_page;
lv_obj_t *contacts_list;
lv_obj_t *keyboard;
lv_obj_t *pinyin;

Contact contacts[50];
int contact_cnt = 0;

char curr_user[100];

char emoji_paths[50][512];
int emoji_cnt = 0;

void chat_page_style_init()
{
    info.name = "/mnt/hgfs/share/simkai.ttf";
    info.weight = 20;
    info.style = FT_FONT_STYLE_NORMAL;
    info.mem = NULL;
    if(!lv_ft_font_init(&info)) {
        LV_LOG_ERROR("create failed.");
    }

    lv_style_init(&style);
    lv_style_set_text_font(&style, info.font);
}

void show_chat_page()
{
    chat_page_style_init();

    chat_page = lv_obj_create(lv_scr_act());
    lv_obj_set_size(chat_page, 800, 480);
    lv_obj_set_scroll_dir(chat_page, LV_DIR_VER);

    lv_obj_t *lb_welcome = lv_label_create(chat_page);
    lv_obj_add_style(lb_welcome, &style, 0);
    char lb_text[200] = {0};
    snprintf(lb_text, sizeof(lb_text), "%s，欢迎你", curr_user);
    lv_label_set_text(lb_welcome, lb_text);

    contacts_list = lv_list_create(chat_page);
    lv_obj_align_to(contacts_list, lb_welcome, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
    lv_obj_set_size(contacts_list, 200, 410);
    lv_obj_add_style(contacts_list, &style, 0);

    keyboard = lv_keyboard_create(chat_page);
    lv_obj_align_to(keyboard, contacts_list, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_add_flag(keyboard, LV_OBJ_FLAG_HIDDEN);
    lv_obj_add_event_cb(keyboard, keyboard_cb, LV_EVENT_VALUE_CHANGED, NULL);

    pinyin = lv_ime_pinyin_create(chat_page);
    lv_ime_pinyin_set_keyboard(pinyin, keyboard);
    lv_obj_set_style_text_font(pinyin, info.font, 0);
    lv_ime_pinyin_set_dict(pinyin, my_dict);

    lv_timer_create(contacts_list_update_task, 100, NULL);
    lv_timer_create(msg_update_task, 100, NULL);
    lv_timer_create(file_update_task, 100, NULL);
    lv_timer_create(emoji_update_task, 100, NULL);
}

void keyboard_cb(lv_event_t *e)
{
    const char *text = lv_keyboard_get_btn_text(keyboard, lv_keyboard_get_selected_btn(keyboard));
    if(strcmp(text, LV_SYMBOL_OK) == 0)
    {
        lv_obj_add_flag(keyboard, LV_OBJ_FLAG_HIDDEN);
        lv_obj_scroll_to_y(chat_page, 0, LV_ANIM_ON);
    }
}

void contacts_list_update_task(lv_timer_t *timer)
{
    if(list_need_update)
    {
        lv_obj_clean(contacts_list);
        lv_obj_t *lb_title = lv_list_add_text(contacts_list, "联系人");

        char *p = strtok(new_list_data, "#");
        while((p = strtok(NULL, "#")) != NULL)
        {
            bool created = false;
            if(strcmp(p, curr_user) == 0)  continue;  // 跳过当前用户
            lv_obj_t *btn = lv_list_add_btn(contacts_list, NULL, p);
            lv_obj_set_style_bg_color(btn, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
            lv_obj_set_style_bg_color(btn, lv_color_hex(0xe6e6e6), LV_STATE_CHECKED);

            for(int i = 0; i < contact_cnt; i++)
            {
                if(strcmp(p, contacts[i].nickname) == 0)  // 聊天页面已存在
                {
                    created = true;
                    break;
                }
            }
            if(!created)
            {
                // 聊天页面不存在，则创建聊天页面
                create_msg_page(p);
            }

            lv_obj_add_event_cb(btn, contacts_list_btn_cb, LV_EVENT_CLICKED, NULL);
        }
        list_need_update = false;
    }
}

void contacts_list_btn_cb(lv_event_t *e)
{
    lv_obj_t *btn = lv_event_get_target(e);

    // 遍历列表里的所有子对象
    uint32_t child_cnt = lv_obj_get_child_cnt(contacts_list);  // 子对象数量
    for(uint32_t i = 0; i < child_cnt; i++)
    {
        lv_obj_t *child = lv_obj_get_child(contacts_list, i);
        if(lv_obj_has_class(child, &lv_btn_class))  // 如果是按钮
        {
            lv_obj_clear_state(child, LV_STATE_CHECKED);  // 取消选中状态
        }
    }

    // 给当前按钮添加选中状态
    lv_obj_add_state(btn, LV_STATE_CHECKED);

    char *nickname = lv_list_get_btn_text(contacts_list, btn);
    for(int i = 0; i < contact_cnt; i++)
    {
        if(strcmp(nickname, contacts[i].nickname) == 0)
        {
            // 显示按钮对应的聊天页面
            lv_obj_clear_flag(contacts[i].msg_page, LV_OBJ_FLAG_HIDDEN);

            child_cnt = lv_obj_get_child_cnt(contacts[i].send_area[CHAT]);  // 子对象数量
            for(uint32_t j = 0; j < child_cnt; j++)
            {
                lv_obj_t *child = lv_obj_get_child(contacts[i].send_area[CHAT], j);
                if(lv_obj_has_class(child, &lv_textarea_class))
                {
                    lv_keyboard_set_textarea(keyboard, child);
                    break;
                }
            }
        }
        else
        {
            // 隐藏其他聊天页面
            lv_obj_add_flag(contacts[i].msg_page, LV_OBJ_FLAG_HIDDEN);
        }
    }
}

void create_msg_page(char *nickname)
{
    contacts[contact_cnt].num = contact_cnt;
    strncpy(contacts[contact_cnt].nickname, nickname, sizeof(contacts[contact_cnt].nickname));

    contacts[contact_cnt].msg_page = lv_obj_create(chat_page);
    lv_obj_align_to(contacts[contact_cnt].msg_page, contacts_list, LV_ALIGN_OUT_RIGHT_TOP, 10, -40);
    lv_obj_set_size(contacts[contact_cnt].msg_page, 550, 450);
    lv_obj_set_style_pad_all(contacts[contact_cnt].msg_page, 0, 0);

    lv_obj_add_flag(contacts[contact_cnt].msg_page, LV_OBJ_FLAG_HIDDEN);

    lv_obj_t *obj_title = lv_obj_create(contacts[contact_cnt].msg_page);
    lv_obj_set_size(obj_title, LV_PCT(100), LV_PCT(10));
    lv_obj_set_style_pad_all(obj_title, 0, 0);
    lv_obj_t *lb_contact = lv_label_create(obj_title);
    lv_obj_align(lb_contact, LV_ALIGN_TOP_LEFT, 10, 6);
    lv_label_set_text(lb_contact, nickname);
    lv_obj_add_style(lb_contact, &style, 0);
    
    contacts[contact_cnt].msg_area = lv_obj_create(contacts[contact_cnt].msg_page);
    lv_obj_align_to(contacts[contact_cnt].msg_area, obj_title, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_size(contacts[contact_cnt].msg_area, LV_PCT(100), LV_PCT(60));
    lv_obj_set_scroll_dir(contacts[contact_cnt].msg_area, LV_DIR_VER);  // 只垂直滚动
    lv_obj_set_flex_flow(contacts[contact_cnt].msg_area, LV_FLEX_FLOW_COLUMN);  // 竖直排列
    lv_obj_set_style_pad_right(contacts[contact_cnt].msg_area, 0, 0);

    lv_obj_t *select_list = lv_list_create(contacts[contact_cnt].msg_page);
    lv_obj_align_to(select_list, contacts[contact_cnt].msg_area, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_size(select_list, LV_PCT(100), LV_PCT(10));
    lv_obj_set_flex_flow(select_list, LV_FLEX_FLOW_ROW);  // 水平排列
    lv_obj_set_scroll_dir(select_list, LV_DIR_HOR);
    lv_obj_add_style(select_list, &style, 0);

    lv_obj_t *btn_chat = lv_list_add_btn(select_list, NULL, "聊天");
    lv_obj_set_width(btn_chat, 80);
    lv_obj_add_state(btn_chat, LV_STATE_CHECKED);
    lv_obj_set_style_bg_color(btn_chat, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(btn_chat, lv_color_hex(0xe6e6e6), LV_STATE_CHECKED);
    lv_obj_add_event_cb(btn_chat, select_list_btn_cb, LV_EVENT_CLICKED, &contacts[contact_cnt].num);

    lv_obj_t *btn_file = lv_list_add_btn(select_list, NULL, "文件");
    lv_obj_set_width(btn_file, 80);
    lv_obj_clear_state(btn_file, LV_STATE_CHECKED);  // 取消选中状态
    lv_obj_set_style_bg_color(btn_file, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(btn_file, lv_color_hex(0xe6e6e6), LV_STATE_CHECKED);
    lv_obj_add_event_cb(btn_file, select_list_btn_cb, LV_EVENT_CLICKED, &contacts[contact_cnt].num);

    lv_obj_t *btn_emoji = lv_list_add_btn(select_list, NULL, "表情");
    lv_obj_set_width(btn_emoji, 80);
    lv_obj_clear_state(btn_emoji, LV_STATE_CHECKED);  // 取消选中状态
    lv_obj_set_style_bg_color(btn_emoji, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(btn_emoji, lv_color_hex(0xe6e6e6), LV_STATE_CHECKED);
    lv_obj_add_event_cb(btn_emoji, select_list_btn_cb, LV_EVENT_CLICKED, &contacts[contact_cnt].num);

    contacts[contact_cnt].send_area[CHAT] = lv_obj_create(contacts[contact_cnt].msg_page);
    lv_obj_align_to(contacts[contact_cnt].send_area[CHAT], select_list, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_size(contacts[contact_cnt].send_area[CHAT], LV_PCT(100), LV_PCT(20));
    lv_obj_set_style_pad_all(contacts[contact_cnt].send_area[CHAT], 0, 0);
    lv_obj_set_style_border_width(contacts[contact_cnt].send_area[CHAT], 0, 0);

    lv_obj_t *textarea_send_msg = lv_textarea_create(contacts[contact_cnt].send_area[CHAT]);
    lv_obj_set_size(textarea_send_msg, LV_PCT(80), LV_PCT(100));
    lv_obj_add_style(textarea_send_msg, &style, 0);
    lv_textarea_set_placeholder_text(textarea_send_msg, "请输入要发送的消息");
    lv_obj_add_event_cb(textarea_send_msg, textarea_cb, LV_EVENT_ALL, NULL);

    lv_obj_t *btn_send_msg = lv_btn_create(contacts[contact_cnt].send_area[CHAT]);
    lv_obj_align_to(btn_send_msg, textarea_send_msg, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
    lv_obj_set_size(btn_send_msg, LV_PCT(20), LV_PCT(100));
    lv_obj_t *lb_send_msg = lv_label_create(btn_send_msg);
    lv_obj_add_style(lb_send_msg, &style, 0);
    lv_label_set_text(lb_send_msg, "发送");
    lv_obj_center(lb_send_msg);
    lv_obj_add_event_cb(btn_send_msg, send_msg_cb, LV_EVENT_CLICKED, &contacts[contact_cnt].num);

    contacts[contact_cnt].send_area[MYFILE] = lv_obj_create(contacts[contact_cnt].msg_page);
    lv_obj_add_flag(contacts[contact_cnt].send_area[MYFILE], LV_OBJ_FLAG_HIDDEN);
    lv_obj_align_to(contacts[contact_cnt].send_area[MYFILE], select_list, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_size(contacts[contact_cnt].send_area[MYFILE], LV_PCT(100), LV_PCT(20));
    lv_obj_set_style_pad_all(contacts[contact_cnt].send_area[MYFILE], 0, 0);
    lv_obj_set_style_border_width(contacts[contact_cnt].send_area[MYFILE], 0, 0);

    lv_obj_t *textarea_send_file = lv_textarea_create(contacts[contact_cnt].send_area[MYFILE]);
    lv_obj_set_size(textarea_send_file, LV_PCT(80), LV_PCT(100));
    lv_obj_add_style(textarea_send_file, &style, 0);
    lv_textarea_set_placeholder_text(textarea_send_file, "请输入文件路径名");
    lv_obj_add_event_cb(textarea_send_file, textarea_cb, LV_EVENT_ALL, NULL);

    lv_obj_t *btn_send_file = lv_btn_create(contacts[contact_cnt].send_area[MYFILE]);
    lv_obj_align_to(btn_send_file, textarea_send_file, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
    lv_obj_set_size(btn_send_file, LV_PCT(20), LV_PCT(100));
    lv_obj_t *lb_send_file = lv_label_create(btn_send_file);
    lv_obj_add_style(lb_send_file, &style, 0);
    lv_label_set_text(lb_send_file, "发送");
    lv_obj_center(lb_send_file);
    lv_obj_add_event_cb(btn_send_file, send_file_cb, LV_EVENT_CLICKED, &contacts[contact_cnt].num);

    contacts[contact_cnt].send_area[EMOJI] = lv_obj_create(contacts[contact_cnt].msg_page);
    lv_obj_add_flag(contacts[contact_cnt].send_area[EMOJI], LV_OBJ_FLAG_HIDDEN);
    lv_obj_align_to(contacts[contact_cnt].send_area[EMOJI], select_list, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    lv_obj_set_size(contacts[contact_cnt].send_area[EMOJI], LV_PCT(100), LV_PCT(20));
    lv_obj_set_style_pad_all(contacts[contact_cnt].send_area[EMOJI], 0, 0);
    lv_obj_set_style_border_width(contacts[contact_cnt].send_area[EMOJI], 0, 0);

    lv_obj_t *emoji_list = lv_list_create(contacts[contact_cnt].send_area[EMOJI]);
    lv_obj_set_size(emoji_list, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_flow(emoji_list, LV_FLEX_FLOW_ROW);  // 水平排列
    lv_obj_set_scroll_dir(emoji_list, LV_DIR_HOR);
    read_emoji(emoji_list);

    contact_cnt++;
}

void select_list_btn_cb(lv_event_t *e)
{
    int *num = (int *)lv_event_get_user_data(e);
    lv_obj_t *btn = lv_event_get_target(e);
    lv_obj_t *list = lv_obj_get_parent(btn);

    // 遍历列表里的所有子对象
    uint32_t child_cnt = lv_obj_get_child_cnt(list);  // 子对象数量
    for(uint32_t i = 0; i < child_cnt; i++)
    {
        lv_obj_t *child = lv_obj_get_child(list, i);
        if(lv_obj_has_class(child, &lv_btn_class))  // 如果是按钮
        {
            lv_obj_clear_state(child, LV_STATE_CHECKED);  // 取消选中状态
        }
    }

    // 给当前按钮添加选中状态
    lv_obj_add_state(btn, LV_STATE_CHECKED);

    const char *text = lv_list_get_btn_text(list, btn);
    if(strcmp(text, "聊天") == 0)
    {
        lv_obj_add_flag(contacts[*num].send_area[MYFILE], LV_OBJ_FLAG_HIDDEN);
        lv_obj_add_flag(contacts[*num].send_area[EMOJI], LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(contacts[*num].send_area[CHAT], LV_OBJ_FLAG_HIDDEN);

        child_cnt = lv_obj_get_child_cnt(contacts[*num].send_area[CHAT]);  // 子对象数量
        for(uint32_t i = 0; i < child_cnt; i++)
        {
            lv_obj_t *child = lv_obj_get_child(contacts[*num].send_area[CHAT], i);
            if(lv_obj_has_class(child, &lv_textarea_class))
            {
                lv_keyboard_set_textarea(keyboard, child);
                break;
            }
        }
    }
    else if(strcmp(text, "文件") == 0)
    {
        lv_obj_add_flag(contacts[*num].send_area[CHAT], LV_OBJ_FLAG_HIDDEN);
        lv_obj_add_flag(contacts[*num].send_area[EMOJI], LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(contacts[*num].send_area[MYFILE], LV_OBJ_FLAG_HIDDEN);

        uint32_t child_cnt = lv_obj_get_child_cnt(contacts[*num].send_area[MYFILE]);  // 子对象数量
        for(uint32_t i = 0; i < child_cnt; i++)
        {
            lv_obj_t *child = lv_obj_get_child(contacts[*num].send_area[MYFILE], i);
            if(lv_obj_has_class(child, &lv_textarea_class))
            {
                lv_keyboard_set_textarea(keyboard, child);
                break;
            }
        }
    }
    else if(strcmp(text, "表情") == 0)
    {
        lv_obj_add_flag(contacts[*num].send_area[CHAT], LV_OBJ_FLAG_HIDDEN);
        lv_obj_add_flag(contacts[*num].send_area[MYFILE], LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(contacts[*num].send_area[EMOJI], LV_OBJ_FLAG_HIDDEN);
    }
}

void textarea_cb(lv_event_t *e)
{
    if(lv_event_get_code(e) == LV_EVENT_CLICKED)
    {
        lv_obj_clear_flag(keyboard, LV_OBJ_FLAG_HIDDEN);
        lv_obj_scroll_to_y(chat_page, lv_obj_get_scroll_bottom(chat_page), LV_ANIM_ON);
    }
}

void read_emoji(lv_obj_t *emoji_list)
{
    const char *folder = EMOJI_SEND_FOLDER_PATH;
    struct dirent *entry;
    DIR *dp = opendir(folder);

    if(dp == NULL)
    {
        perror("opendir");
        return;
    }

    while((entry = readdir(dp)))
    {
        const char *ext = strrchr(entry->d_name, '.');
        if(ext && (strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 
           || strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0))
        {
            char filepath[512] = {0};
            snprintf(filepath, sizeof(filepath), "S:%s/%s", folder, entry->d_name);

            strncpy(emoji_paths[emoji_cnt], filepath, sizeof(emoji_paths[emoji_cnt]));
            
            lv_obj_t *btn = lv_list_add_btn(emoji_list, NULL, NULL);
            lv_obj_set_size(btn, 85, LV_PCT(100));
            lv_obj_set_style_pad_all(btn, 0, 0);
            lv_obj_t *img = lv_img_create(btn);
            lv_img_set_src(img, filepath);
            lv_obj_add_event_cb(btn, send_emoji_cb, LV_EVENT_CLICKED, NULL);
            
            emoji_cnt++;
        }
    }

    closedir(dp);
}

void send_msg_cb(lv_event_t *e)
{
    int *num = (int *)lv_event_get_user_data(e);
    lv_obj_t *msg_area = contacts[*num].msg_area;

    lv_obj_t *textarea;
    uint32_t child_cnt = lv_obj_get_child_cnt(contacts[*num].send_area[CHAT]);  // 子对象数量
    for(uint32_t i = 0; i < child_cnt; i++)
    {
        lv_obj_t *child = lv_obj_get_child(contacts[*num].send_area[CHAT], i);
        if(lv_obj_has_class(child, &lv_textarea_class))
        {
            textarea = child;
            break;
        }
    }
    
    const char *text = lv_textarea_get_text(textarea);
    if(text && strlen(text) > 0)
    {    
        add_message(msg_area, text, true);

        char sbuf[2048] = {0};
        snprintf(sbuf, sizeof(sbuf), "chat@%s@%s\n", contacts[*num].nickname, text);
        send(tcpsock, sbuf, strlen(sbuf), 0);

        lv_textarea_set_text(textarea, "");  // 清空输入框
    }
}

void send_file_cb(lv_event_t *e)
{
    int *num = (int *)lv_event_get_user_data(e);
    lv_obj_t *msg_area = contacts[*num].msg_area;

    lv_obj_t *textarea;
    uint32_t child_cnt = lv_obj_get_child_cnt(contacts[*num].send_area[MYFILE]);  // 子对象数量
    for(uint32_t i = 0; i < child_cnt; i++)
    {
        lv_obj_t *child = lv_obj_get_child(contacts[*num].send_area[MYFILE], i);
        if(lv_obj_has_class(child, &lv_textarea_class))
        {
            textarea = child;
            break;
        }
    }
    
    const char *filepath = lv_textarea_get_text(textarea);
    const char *filename;
    if((filename = strrchr(filepath, '/')) != NULL)  // 给出绝对路径
    {
        filename++;
    }
    else  // 只给文件名
    {
        filename = filepath;
    }

    int fd = open(filepath, O_RDONLY);
    if(fd == -1)
    {
        static const char *btns[] = {""};
        lv_obj_t *msgbox = lv_msgbox_create(lv_scr_act(), "提示", "该文件不存在！", btns, true);
        lv_obj_t *title = lv_msgbox_get_title(msgbox);
        lv_obj_t *text = lv_msgbox_get_text(msgbox);
        lv_obj_add_style(title, &style, 0);
        lv_obj_add_style(text, &style, 0);
        lv_obj_center(msgbox);
        lv_textarea_set_text(textarea, "");  // 清空输入框
        return;
    }

    struct stat mystat;
    int ret = stat(filepath, &mystat);
    if(ret == -1)
    {
        fprintf(stderr, "获取%s属性信息失败:%s\n", filepath, strerror(errno));
        exit(1);
    }

    char text[200] = {0};
    snprintf(text, sizeof(text), "发送了文件：\n%s", filename);
    if(filepath && strlen(filepath) > 0)
    {    
        add_message(msg_area, text, true);

        char sbuf[2048] = {0};
        snprintf(sbuf, sizeof(sbuf), "sendfile@%s@%s@%ld\n", contacts[*num].nickname, filename, mystat.st_size);
        send(tcpsock, sbuf, strlen(sbuf), 0);

        while(1)
        {
            memset(sbuf, 0, sizeof(sbuf));
            ret = read(fd, sbuf, sizeof(sbuf));
            if(ret == 0)
            {
                break;
            }
            send(tcpsock, sbuf, ret, 0);
        }
        close(fd);

        lv_textarea_set_text(textarea, "");  // 清空输入框
    }
}

void send_emoji_cb(lv_event_t *e)
{
    lv_obj_t *btn = lv_event_get_target(e);
    lv_obj_t *emoji_list = lv_obj_get_parent(btn);
    lv_obj_t *send_area = lv_obj_get_parent(emoji_list);

    // 遍历列表里的所有子对象
    uint32_t child_cnt = lv_obj_get_child_cnt(emoji_list);  // 子对象数量
    uint32_t index_emoji;
    for(index_emoji = 0; index_emoji < child_cnt; index_emoji++)
    {
        lv_obj_t *child = lv_obj_get_child(emoji_list, index_emoji);
        if(child == btn)
        {
            break;
        }
    }

    int index_contact;
    for(index_contact = 0; index_contact < contact_cnt; index_contact++)
    {
        if(contacts[index_contact].send_area[EMOJI] == send_area)
        {
            break;
        }
    }

    add_emoji(contacts[index_contact].msg_area, emoji_paths[index_emoji], true);

    const char *emoji_path = emoji_paths[index_emoji] + 2;  // 跳过S:
    const char *emoji_name = strrchr(emoji_path, '/');
    emoji_name++;

    int fd = open(emoji_path, O_RDONLY);
    if(fd == -1)
    {
        fprintf(stderr, "文件%s不存在:%s\n", emoji_path, strerror(errno));
        return;
    }

    struct stat mystat;
    int ret = stat(emoji_path, &mystat);
    if(ret == -1)
    {
        fprintf(stderr, "获取%s属性信息失败:%s\n", emoji_path, strerror(errno));
        return;
    }

    char sbuf[2048] = {0};
    snprintf(sbuf, sizeof(sbuf), "emoji@%s@%s@%ld\n", contacts[index_contact].nickname, emoji_name, mystat.st_size);
    send(tcpsock, sbuf, strlen(sbuf), 0);

    while(1)
    {
        memset(sbuf, 0, sizeof(sbuf));
        ret = read(fd, sbuf, sizeof(sbuf));
        if(ret == 0)
        {
            break;
        }
        send(tcpsock, sbuf, ret, 0);
    }
    close(fd);
}

void msg_update_task(lv_timer_t *timer)
{
    if(msg_need_update)
    {
        char *p = strtok(new_msg_data, "#");
        p = strtok(NULL, "#");
        int i;
        for(i = 0; i < contact_cnt; i++)
        {
            if(strcmp(contacts[i].nickname, p) == 0)
            {
                break;
            }
        }
        p = strtok(NULL, "#");
        add_message(contacts[i].msg_area, p, false);

        msg_need_update = false;
    }
}

void file_update_task(lv_timer_t *timer)
{
    if(file_need_update)
    {
        char *p = strtok(new_file_data_head, "#");
        p = strtok(NULL, "#");  // nickname
        int i;
        for(i = 0; i < contact_cnt; i++)
        {
            if(strcmp(contacts[i].nickname, p) == 0)
            {
                break;
            }
        }
        p = strtok(NULL, "#");  // filename
        char filename[200] = {0};
        strncpy(filename, p, sizeof(filename));
        char text[200] = {0};
        snprintf(text, sizeof(text), "发送了文件：\n%s", filename);
        add_message(contacts[i].msg_area, text, false);

        file_need_update = false;
    }
}

void emoji_update_task(lv_timer_t *timer)
{
    if(emoji_need_update)
    {
        char *p = strtok(new_emoji_data_head, "#");
        p = strtok(NULL, "#");  // nickname
        int i;
        for(i = 0; i < contact_cnt; i++)
        {
            if(strcmp(contacts[i].nickname, p) == 0)
            {
                break;
            }
        }
        p = strtok(NULL, "#");  // emoji_name
        const char *folder = EMOJI_RECV_FOLDER_PATH;
        char emoji_path[512] = {0};
        snprintf(emoji_path, sizeof(emoji_path), "S:%s/%s", folder, p);
        add_emoji(contacts[i].msg_area, emoji_path, false);

        emoji_need_update = false;
    }
}

void add_message(lv_obj_t *msg_area, const char *text, bool is_self)
{
    // 每条消息一整行
    lv_obj_t *msg_row = lv_obj_create(msg_area);
    lv_obj_set_width(msg_row, LV_PCT(100));  // 占满宽度
    lv_obj_set_height(msg_row, LV_SIZE_CONTENT);
    lv_obj_clear_flag(msg_row, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(msg_row, 0, 0);
    lv_obj_set_style_pad_all(msg_row, 0, 0);

    // 内层容器：宽度随内容，可左右浮动
    lv_obj_t *content = lv_obj_create(msg_row);
    lv_obj_set_width(content, LV_SIZE_CONTENT);
    lv_obj_set_height(content, LV_SIZE_CONTENT);
    lv_obj_clear_flag(content, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(content, 0, 0);
    lv_obj_set_style_pad_all(content, 0, 0);

    if(is_self)
    {
        lv_obj_set_style_align(content, LV_ALIGN_RIGHT_MID, 0);  // 靠右
        lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW_REVERSE);  // 头像在右，气泡在左
    }
    else
    {
        lv_obj_set_style_align(content, LV_ALIGN_LEFT_MID, 0);  // 靠左
        lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW);  // 头像在左，气泡在右
    }

    // 头像
    lv_obj_t *avatar = lv_img_create(content);
    lv_img_set_src(avatar, LV_SYMBOL_IMAGE);
    lv_obj_set_size(avatar, 32, 32);

    // 气泡
    lv_obj_t *bubble = lv_obj_create(content);
    lv_obj_set_style_pad_all(bubble, 6, 0);
    lv_obj_set_style_radius(bubble, 8, 0);
    lv_obj_set_width(bubble, LV_SIZE_CONTENT);
    lv_obj_set_height(bubble, LV_SIZE_CONTENT);
    lv_obj_clear_flag(bubble, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(bubble, 0, 0);

    if(is_self)
    {
        lv_obj_set_style_bg_color(bubble, lv_palette_main(LV_PALETTE_BLUE), 0);
        lv_obj_set_style_text_color(bubble, lv_color_white(), 0);
    }
    else
    {
        lv_obj_set_style_bg_color(bubble, lv_palette_main(LV_PALETTE_LIGHT_GREEN), 0);
        lv_obj_set_style_text_color(bubble, lv_color_black(), 0);
    }

    // 文本
    lv_obj_t *lb_msg = lv_label_create(bubble);
    lv_obj_set_width(lb_msg, lv_obj_get_width(msg_area) * 0.3);
    lv_obj_add_style(lb_msg, &style, 0);
    lv_label_set_long_mode(lb_msg, LV_LABEL_LONG_WRAP);  // 允许换行
    lv_label_set_text(lb_msg, text);

    // 滚动到底部
    lv_obj_scroll_to(msg_area, 0, LV_COORD_MAX, LV_ANIM_ON);
}

void add_emoji(lv_obj_t *msg_area, const char *emoji_path, bool is_self)
{
    // 每条消息一整行
    lv_obj_t *msg_row = lv_obj_create(msg_area);
    lv_obj_set_width(msg_row, LV_PCT(100));  // 占满宽度
    lv_obj_set_height(msg_row, LV_SIZE_CONTENT);
    lv_obj_clear_flag(msg_row, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(msg_row, 0, 0);
    lv_obj_set_style_pad_all(msg_row, 0, 0);

    // 内层容器：宽度随内容，可左右浮动
    lv_obj_t *content = lv_obj_create(msg_row);
    lv_obj_set_width(content, LV_SIZE_CONTENT);
    lv_obj_set_height(content, LV_SIZE_CONTENT);
    lv_obj_clear_flag(content, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(content, 0, 0);
    lv_obj_set_style_pad_all(content, 0, 0);

    if(is_self)
    {
        lv_obj_set_style_align(content, LV_ALIGN_RIGHT_MID, 0);  // 靠右
        lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW_REVERSE);  // 头像在右，气泡在左
    }
    else
    {
        lv_obj_set_style_align(content, LV_ALIGN_LEFT_MID, 0);  // 靠左
        lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW);  // 头像在左，气泡在右
    }

    // 头像
    lv_obj_t *avatar = lv_img_create(content);
    lv_img_set_src(avatar, LV_SYMBOL_IMAGE);
    lv_obj_set_size(avatar, 32, 32);

    lv_obj_t *img = lv_img_create(content);
    lv_img_set_src(img, emoji_path);

    // 滚动到底部
    lv_obj_scroll_to(msg_area, 0, LV_COORD_MAX, LV_ANIM_ON);
}